package com.susgame.core.util;

import java.util.Random;

public class SusRandom {
	private Random rand = new Random();
	private long seed;
	private static final SusRandom instance = new SusRandom();

	private SusRandom() {
		this.seed = System.currentTimeMillis();
		this.rand.setSeed(this.seed);
	}

	private void checkSeed() {
		long now = System.currentTimeMillis();
		if (now - this.seed > 3600000L) {
			this.seed = now;
			this.rand.setSeed(this.seed);
		}
	}

	public static SusRandom getInstance() {
		instance.checkSeed();
		return instance;
	}

	public int getRandom(int range, boolean hasZero) {
		try {
			if (range == 0) {
				return 0;
			}

			if (!hasZero) {
				return getRandom(1, range);
			}

			return getRandom(0, range);
		} catch (IllegalArgumentException exception) {
			throw new IllegalArgumentException(exception.getMessage()
					+ " input num is:" + range);
		}
		
	}

	public int getRandom(int begin, int end) {
		try {
			if (end <= begin) {
				return begin;
			}
			int randNum = this.rand.nextInt(1 + end - begin);
			return randNum + begin;
		} catch (IllegalArgumentException exception) {
			throw new IllegalArgumentException(exception.getMessage()
					+ " input num is:" + begin + " and " + end);
		}
		
	}

	public double getRndNumP(double pSngBegin, double pSngEnd, double pSngPB,
			double pSngPE, double pBytP) {
		double preferRange = pSngPE - pSngPB;
		double randTotalRange = pSngEnd - pSngBegin;

		if (preferRange / randTotalRange * 100.0D == pBytP) {
			return getRandomNum(pSngBegin, pSngEnd);
		}

		double sngIncreased = (pBytP / 100.0D * randTotalRange - preferRange)
				/ (1.0D - pBytP / 100.0D);

		double sngResult = getRandomNum(pSngBegin, pSngEnd + sngIncreased);

		if ((pSngBegin <= sngResult) && (sngResult <= pSngPB)) {
			return sngResult;
		}
		if ((pSngPB <= sngResult) && (sngResult <= pSngPE + sngIncreased)) {
			return pSngPB + (sngResult - pSngPB) * preferRange
					/ (preferRange + sngIncreased);
		}
		if ((pSngPE + sngIncreased <= sngResult)
				&& (sngResult <= pSngEnd + sngIncreased)) {
			return sngResult - sngIncreased;
		}

		return 0.0D;
	}

	private double getRandomNum(double pSngBegin, double pSngEnd) {
		return (pSngEnd - pSngBegin) * Math.random() + pSngBegin;
	}

	public double getRndNumP2(double pSngBegin, double pSngEnd, double pSngPB,
			double pSngPE, double pBytP) {
		double sngPLen = pSngPE - pSngPB;
		double sngTLen = pSngEnd - pSngBegin;

		if (sngPLen / sngTLen * 100.0D == pBytP) {
			return getRandomNum2(pSngBegin, pSngEnd);
		}

		double sngIncreased = (pBytP / 100.0D * sngTLen - sngPLen)
				/ (1.0D - pBytP / 100.0D);

		double sngResult = getRandomNum2(pSngBegin, pSngEnd + sngIncreased);

		if ((pSngBegin <= sngResult) && (sngResult <= pSngPB)) {
			return sngResult;
		}
		if ((pSngPB <= sngResult) && (sngResult <= pSngPE + sngIncreased)) {
			return pSngPB + (sngResult - pSngPB) * sngPLen
					/ (sngPLen + sngIncreased);
		}
		if ((pSngPE + sngIncreased <= sngResult)
				&& (sngResult <= pSngEnd + sngIncreased)) {
			return sngResult - sngIncreased;
		}

		return 0.0D;
	}

	private double getRandomNum2(double pSngBegin, double pSndEnd) {
		int randNum = this.rand
				.nextInt((int) (pSndEnd * 100.0D - pSngBegin * 100.0D));
		return randNum / 100.0D + pSngBegin;
	}
}
